package start

import (
	"fmt"
	"gitee.com/filters/logger"
	"gitee.com/filters/reader/wviper"
	"gitee.com/filters/start/refer"
	"gitee.com/filters/start/safe_map"
	"gitee.com/filters/utils/conversion"
	"github.com/gin-gonic/gin"
	"github.com/robfig/cron/v3"
	"github.com/spf13/cast"
)

const (
	GinConfig = "Ginserver"
	RunMode   = "run_mode"
	HttpPort  = "http_port"
)

type GinServer struct {
	ginConfig safe_map.ConfigSafeMap
	engine    *gin.Engine
}

func NewGin(opt ...wviper.Option) *GinServer {
	s := &GinServer{
		engine: gin.Default(),
	}
	err := s.LoadConfig(opt...)
	if err != nil {
		panic(err)
	}
	return s
}

func (g *GinServer) LoadConfig(opt ...wviper.Option) error {
	cfg, err := wviper.NewSetting(opt...)
	if err != nil {
		return err
	}
	config = cfg
	if _, ok := cfg.Get(GinConfig).(map[string]interface{}); !ok {
		return refer.ErrorNotFoundConfigInfo
	}
	g.ginConfig.Data = cfg.Get(GinConfig).(map[string]interface{})
	return nil
}

func (g *GinServer) Run() error {
	gin.SetMode(g.ginConfig.Data[RunMode].(string))
	fmt.Printf("http server:%s \n", fmt.Sprintf("http://127.0.0.1:%d", g.ginConfig.Data[HttpPort].(int)))
	err := g.engine.Run(":" + cast.ToString(g.ginConfig.Data[HttpPort].(int)))
	if err != nil {
		return err
	}
	return nil
}

// UseLog 日志记录
func (g *GinServer) UseLog() *GinServer {
	cfg := config.Get(logger.Logger).(map[string]interface{})
	logger.NewLog(logger.WithWritePath(cfg[logger.LogPathName].(string)),
		logger.WithLogExt(cfg[logger.LogExtName].(string))).CurLog().WrapFormat()
	return g
}

// BindField 绑定数据
func (g *GinServer) BindField(f ...interface{}) *GinServer {
	for _, i2 := range f {
		conversion.ToStruct(config.AllSettings(), i2)
	}
	return g
}

// HandleMiddleware 绑定中间件
func (g *GinServer) HandleMiddleware(middles ...gin.HandlerFunc) *GinServer {
	g.engine.Use(middles...)
	return g
}

// HandleAddFunc 定时执行函数
func (g *GinServer) HandleAddFunc(list []*CronTabObj) *GinServer {
	c := cron.New(cron.WithSeconds())
	for index, crontabObj := range list {
		func(id int, obj *CronTabObj) {
			_, _ = c.AddJob(
				obj.CronTab, //一分钟
				cron.FuncJob(func() {
					_ = obj.Handler()
				}))
		}(index, crontabObj)
	}
	c.Start() //启动crond
	return g
}

// HandleRouter 绑定路由
func (g *GinServer) HandleRouter(route func(r *gin.Engine)) *GinServer {
	route(g.engine)
	return g
}
